package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.ConfigConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.log.entity.LoginLogEntity;
import com.xbongbong.paas.log.model.LoginLogModel;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.redis.RedisTimeConstant;
import com.xbongbong.paas.service.CompanyService;
import com.xbongbong.paas.service.LoginService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.DesUtil;
import com.xbongbong.paas.toolbox.util.DigestUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.util.URLEncodeUtils;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.login.pojo.dto.AutoLoginDTO;
import com.xbongbong.pro.login.pojo.vo.AutoLoginVO;
import com.xbongbong.pro.packageInfo.pojo.vo.CheckPackageVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.domain.entity.UserConfigEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.enums.UserConfigEnum;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.UserConfigModel;
import com.xbongbong.sys.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * 登录服务
 * @author kaka
 * @date 2019/4/18 9:35
 * @since v1.0
 * @version v1.0
 */
@Service("loginService")
public class LoginServiceImpl implements LoginService {

    private static  final Logger LOG = LoggerFactory.getLogger(LoginServiceImpl.class);

    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private UserModel userModel;
    @Resource
    private CompanyService companyService;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private UserConfigModel userConfigModel;
    @Resource
    private LoginLogModel loginLogModel;

    @Override
    public AutoLoginVO autoLogin(AutoLoginDTO autoLoginDTO, HttpServletRequest request, HttpServletResponse httpResponse) throws XbbException {
        AutoLoginVO autoLoginVO = new AutoLoginVO();
        String nonce = autoLoginDTO.getNonce();
        String userIdCorpidDES = autoLoginDTO.getT();
        String redirectUrl = autoLoginDTO.getRurl();

        if(StringUtil.isEmpty(nonce) || StringUtil.isEmpty(userIdCorpidDES)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }

        //URLDecode 空格修正
        userIdCorpidDES = URLEncodeUtils.decodeURL(userIdCorpidDES).replaceAll(" ", "+");
        //解密userId, corpid
        String userId_corpId;
        try {
            userIdCorpidDES = userIdCorpidDES.replaceAll("%2f", "/");
            userId_corpId = DesUtil.decrypt(userIdCorpidDES, ConfigConstant.DES_DEFAULT_KEY);
            //解析userId中的特殊符号
            userId_corpId = URLEncodeUtils.decodeURL(userId_corpId);
        } catch (Exception e) {
            LOG.error("解密userId时出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        // 增加nonce的判断
        String cachedNonce = paasRedisHelper.getValue(RedisPrefixConstant.USER_AUTO_LOGIN_NONCE, userId_corpId);
        if (StringUtil.isEmpty(cachedNonce) || !nonce.equals(cachedNonce)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100012);
        }

        //userInfo[0] : userId; userInfo[1] : corpId;
        String[] userInfo = userId_corpId.split("____");

        //登录成功
        UserEntity userEntity = userModel.getByKey(userInfo[0], userInfo[1]);

        //不在可見范圍的管理員进入设置页
        if(null == userEntity){
           throw new XbbException(SystemErrorCodeEnum.API_ERROR_100004);
        }

        String xbbAccessToken = paasRedisHelper.getValue(RedisPrefixConstant.XBB_ACCESS_TOKEN, userId_corpId);
        //如果不存在accessToken，再去生成
        if(xbbAccessToken == null || "".equals(xbbAccessToken)){
            //生成接口的accessToken,存cookie
            xbbAccessToken = "xbbAccessToken" + System.currentTimeMillis() + userId_corpId;
            xbbAccessToken = DigestUtil.Encrypt(xbbAccessToken, "SHA-256");
        }
        //过期时间，默认一天,前端会放localStorage不用再塞在cookie里
        paasRedisHelper.setValue(RedisPrefixConstant.XBB_ACCESS_TOKEN, userId_corpId, xbbAccessToken, TimeConstant.SECONDS_PER_DAY);

        autoLoginVO.setCorpid(userInfo[1]);
        autoLoginVO.setUserId(userInfo[0]);
        autoLoginVO.setXbbAccessToken(xbbAccessToken);

        //套餐限制
        String corpid = userInfo[1];
        CheckPackageVO checkPackageVO = companyService.checkPackage(corpid);
        if (Objects.equals(checkPackageVO.getIsActive(), BasicConstant.ZERO)) {
            autoLoginVO.setCode(SystemErrorCodeEnum.API_ERROR_100070.getCode());
            autoLoginVO.setMsg(checkPackageVO.getShowMsg());
            // 超过套餐类型
            JSONObject packageInfo = companyService.handlePackageErrorInfo(userEntity, checkPackageVO.getExpireType());
            autoLoginVO.setPackageErrorInfo(packageInfo);

            // 获取钉钉服务群信息
            CompanyConfigEntity companyConfigEntity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.DINGTALK_GOODS_CODE.getAlias(), StringConstant.DEFAULT_CORPID);
            if (Objects.nonNull(companyConfigEntity)) {
                JSONObject goodsCodeObj = JsonHelperUtil.parseObject(companyConfigEntity.getConfigValue());
                autoLoginVO.setGoodsCode(goodsCodeObj.getString("goodsCode"));
                autoLoginVO.setToken(goodsCodeObj.getString("token"));
            }

            return autoLoginVO;
        }

        //登录日志
        LoginLogEntity loginLog = new LoginLogEntity(corpid, userEntity.getUserId(), userEntity.getName(), "dingtalkPc", request);
        try {
            loginLogModel.insert(loginLog);
        } catch (XbbException e) {
            LOG.error("autoLogin 添加登陆日志出错 : ", e);
        }

        // 获取国际化标示
        String lang = getWebI18nPack(userEntity);
        autoLoginVO.setLang(lang);

        autoLoginVO.setRurl(redirectUrl);
        autoLoginVO.setFeeType(checkPackageVO.getFeeType());
        return autoLoginVO;
    }


    /**
     *  获取web端国际化配置参数
     *  先从redis中获取，找不到则从tb_company_config中查
     * @param userEntity 用户
     * @return 该公司的国际化标示，默认为zh_CN
     */
    private String getWebI18nPack(UserEntity userEntity) {
        String key = userEntity.getCorpid() + "_" + userEntity.getUserId();
        String lang = paasRedisHelper.getValue(RedisPrefixConstant.PC_I18N_PACK, key);
        if (StringUtil.isEmpty(lang)) {
            UserConfigEntity userConfigEntity = userConfigModel.getByUserId(userEntity.getUserId(), userEntity.getCorpid(), UserConfigEnum.I18N_PACK.getAlias());
            //CompanyConfigEntity companyConfig = companyConfigModel.getByConfigAlias(CompanyConfigEnum.PC_I18N_PACK.getAlias(), corpid);
            if (userConfigEntity == null) {
                lang = "zh_CN";
            } else {
                lang = userConfigEntity.getConfigValue();
            }
            paasRedisHelper.setValue(RedisPrefixConstant.PC_I18N_PACK, key, lang, RedisTimeConstant.LONG_DURATION);
        }
        return lang;
    }
}
